<template>
  <Drawer
    :visible="visible"
    :title="type === 1 ? '新增角色' : '编辑角色'"
    size="large"
    @ok="handleOk"
    @close="handleCancel"
  >
    <template #footer>
      <Button class="float-right ml-10px" key="submit" type="primary" @click="handleOk">确认</Button>
      <Button class="float-right" key="back" @click="handleCancel">返回</Button>
    </template>
    <div class="centent">
      <Form
        ref="formRef"
        :model="formState"
        :rules="rules"
        :labelCol="{ style: { width: '80px' } }"
        :wrapper-col="{ style: { width: '180px' } }"
        :colon="false"
      >
        <FormItem label="应用" name="appId">
          <Select
            v-model:value="formState.appId"
            :field-names="{ label: 'name', value: 'appId' }"
            :options="appSelectList"
            placeholder="请选择应用"
          >
            <SelectOption v-for="option in appSelectList" v-bind:key="option.appId" :value="option.appId"
              >{{ option.name }}
            </SelectOption>
          </Select>
        </FormItem>
        <FormItem label="角色名称" name="name">
          <Input v-model:value="formState.name" placeholder="请输入角色名称" />
        </FormItem>
        <FormItem label="角色编码" name="code">
          <Input v-model:value="formState.code" placeholder="请输入角色编码" />
        </FormItem>
        <FormItem label="状态" name="status" valuePropName="formState.status">
          <Switch
            v-model:value="formState.status"
            checked-children="启用"
            un-checked-children="停用"
            :checkedValue="true"
            :unCheckedValue="false"
            v-model:checked="formState.status"
            @change="changeStatus"
          />
        </FormItem>
        <FormItem label="角色描述" name="description">
          <Textarea v-model:value="formState.description" placeholder="请输入角色描述" />
        </FormItem>
        <FormItem label="应用资源" name="resourceIdList" v-show="flag">
          <Tree
            :showLine="false"
            checkable
            :fieldNames="{ key: 'id', title: 'name', children: 'children' }"
            style="font-weight: bolder; text-align: right"
            v-model:checkedKeys="formState.resourceIdList"
            :tree-data="treeData"
            :autoExpandParent="false"
            checkStrictly
            @check="handleSelect"
          >
            <template #title="{ title, type }">
              <span>
                <Tag color="pink" v-if="type === 'MENU'">{{ type }}</Tag>
                <Tag color="blue" v-if="type === 'ELEMENT'">{{ type }}</Tag>
                {{ title }}
              </span>
            </template>
          </Tree>
        </FormItem>
      </Form>
    </div>
  </Drawer>
</template>
<script setup lang="ts">
/* eslint-disable */
import { ref, defineProps, reactive, watch, unref } from 'vue';
import {
  Form,
  Drawer,
  Select,
  SelectOption,
  FormItem,
  Input,
  message,
  Tree,
  Button,
  Switch,
  Textarea,
  TreeProps,
  Tag,
} from 'ant-design-vue';
import { createSaaSRole, editSaaSRole, getAppResourceTree, getSaaSRoleDetail } from '/@/api/authority-mgmt/role';
import { getTenantSideApps } from '/@/api/deployment-center/deployTask';
import { getSubAppList } from '/@/api/organization-mgmt/user';
import { ApiResultEnum } from '/@/enums/resEnum';

const rules = {
  name: [
    {
      trigger: 'brlu',
      required: true,
      message: '请输入角色名称',
    },
    {
      trigger: 'change',
      min: 1,
      message: '至少输入1位字符',
    },
    {
      trigger: 'change',
      max: 32,
      message: '字符数不超过32位',
    },
  ],
  code: [
    {
      trigger: 'change',
      required: true,
      message: '请输入角色编码',
    },
    {
      trigger: 'change',
      min: 1,
      message: '至少输入1位字符',
    },
    {
      trigger: 'change',
      max: 32,
      message: '字符数不超过32位',
    },
  ],
  description: [
    {
      trigger: 'change',
      min: 1,
      message: '至少输入1位字符',
    },
    {
      trigger: 'change',
      max: 255,
      message: '字符数不超过255位',
    },
  ],
};

let props = defineProps({
  visible: Boolean,
  type: Number,
  data: Object,
});
let visible = ref(props.visible);
const appSelectList = ref();
let type = ref(props.type);
const formRef = ref();
const flag = ref(false);

interface Role {
  id: string;
  name: string;
  appId: string;
  code: string;
  status: boolean;
  description: string;
  resourceIdList: string[];
}

let formState = ref<Partial<Role>>({});

const treeData = ref<TreeProps['treeData']>([]);

function resetForm() {
  formRef.value.resetFields();
}

const emit = defineEmits(['close']);
const handleOk = async () => {
  formRef.value.validate().then(async () => {
    const values = { ...formState.value };
    if (props.type === 1) {
      if (values.status == null) {
        values.status = false;
      }
      const res = await createSaaSRole(values);
      if (res) {
        message.success(ApiResultEnum.ADD_SUCCESS);
        resetForm();
        emit('close', 'success');
      } else {
        message.error(ApiResultEnum.ADD_FAIL);
        emit('close', 'close');
      }
    } else {
      const res = await editSaaSRole(values);
      if (res) {
        message.success(ApiResultEnum.UPDATA_SUCCESS);
        emit('close', 'success');
      } else {
        message.error(ApiResultEnum.UPDATA_FAIL);
        emit('close', 'close');
      }
    }
  });
};
const handleCancel = () => {
  resetForm();
  emit('close', 'close');
};
const changeStatus = (checked: any) => {
  formState.value.status = checked;
};

const handleChecked = (node) => {
  const childrenNodeIdList = getNodeChildrenIdList(node);
  const parentNodeIdList = getParentNode(node);
  const { checked } = formState.value.resourceIdList;
  formState.value.resourceIdList = [...checked, ...childrenNodeIdList, ...parentNodeIdList];
};
const handleDischecked = (node) => {
  const childrenNodeIdList = getNodeChildrenIdList(node);
  const { checked } = formState.value.resourceIdList;
  formState.value.resourceIdList = checked.filter((item) => !childrenNodeIdList.includes(item));
};

const getNodeChildrenIdList = (node) => {
  let _nodeList = [];

  function traverse(node, nodeList) {
    if (node.children) {
      for (let child of node.children) {
        _nodeList.push(child.id);
        if (child.children) {
          traverse(child, nodeList);
        }
      }
    }
  }

  traverse(node, _nodeList);

  return _nodeList;
};

const getParentNode = (node) => {
  let _parentList = [];

  function findParents(node, parentList) {
    if (node.parent) {
      parentList.push(node.parent.node.id);
      if (node.parent.parent) {
        findParents(node.parent, parentList);
      }
    }
  }
  findParents(node, _parentList);
  return _parentList;
};
const handleSelect = (value, ...rest) => {
  const { checked, node } = rest[0];
  if (checked) {
    handleChecked(node);
  } else {
    handleDischecked(node);
  }
};

async function getRoleDetail() {
  // eslint-disable-next-line camelcase
  flag.value = true;
  const res = await getSaaSRoleDetail({ role_id: props.data?.id });
  formState.value.id = props.data?.id;
  formState.value.appId = res.appId;
  formState.value.code = res.code;
  formState.value.description = res.description;
  formState.value.name = res.name;
  formState.value.status = res.status;
  getAppResourceTree({ appId: formState.value.appId }).then((info) => {
    treeData.value = info;
    formState.value.resourceIdList = res.resourceIdList;
  });
}

watch(props, async (newValue) => {
  visible.value = newValue.visible;
  if (visible.value === true) {
    type.value = newValue.type;
    flag.value = false;
    appSelectList.value = await getSubAppList();

    if (type.value === 1) {
      resetForm();
    }
    // 编辑
    if (type.value === 2) {
      getRoleDetail();
    }
  }
});

watch(
  () => formState.value.appId,
  async () => {
    if (formState.value.appId) {
      flag.value = true;
      treeData.value = await getAppResourceTree({ appId: formState.value.appId });
    }
  }
);
</script>
